/*
 * CC3OpenGLES11Textures.m
 *
 * cocos3d 0.6.1
 * Author: Bill Hollings
 * Copyright (c) 2011 The Brenwill Workshop Ltd. All rights reserved.
 * http://www.brenwill.com
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 * 
 * The above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.
 * 
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 * THE SOFTWARE.
 *
 * http://en.wikipedia.org/wiki/MIT_License
 * 
 * See header file CC3OpenGLES11Textures.h for full API documentation.
 */

#include "CC3OpenGLES11Textures.h"
#include "CCArray.h"
#include "CC3OpenGLES11Engine.h"


#pragma mark -
#pragma mark CC3OpenGLES11StateTrackerActiveTexture

//@implementation CC3OpenGLES11StateTrackerActiveTexture
//
//+(CC3GLESStateOriginalValueHandling) defaultOriginalValueHandling {
//	return kCC3GLESStateOriginalValueReadOnceAndRestore;
//}
//
//-(GLenum) glEnumValue {
//	return GL_TEXTURE0 + value;
//}
//
//-(void) setGLValue {
//	if( setGLFunction ) {
//		setGLFunction(self.glEnumValue);
//	}
//}
//
//-(void) getGLValue {
//	[super getGLValue];
//	originalValue -= GL_TEXTURE0;
//}
//
//-(NSString*) description {
//	return [NSString stringWithFormat: @"%@ %@ = %u (orig %u)",
//			[self class], NSStringFromGLEnum(self.name), self.value, self.originalValue];
//}
//
//@end

CC3OpenGLES11StateTrackerActiveTexture* CC3OpenGLES11StateTrackerActiveTexture::trackerForState(GLenum aName, CC3SetGLEnumerationFunction* setGLFunc)
{
	CC3OpenGLES11StateTrackerActiveTexture* pState = new CC3OpenGLES11StateTrackerActiveTexture;
	if (pState) 
	{
		pState->initForState(aName, setGLFunc);
		pState->autorelease();
	}
	
	return pState;
}

CC3GLESStateOriginalValueHandling CC3OpenGLES11StateTrackerActiveTexture::defaultOriginalValueHandling()
{
	return kCC3GLESStateOriginalValueReadOnceAndRestore;
}

GLenum CC3OpenGLES11StateTrackerActiveTexture::glEnumValue()
{
	return GL_TEXTURE0 + value;
}

void CC3OpenGLES11StateTrackerActiveTexture::setGLValue()
{
	if( setGLFunction ) 
	{
		setGLFunction(glEnumValue());
	}
}

void CC3OpenGLES11StateTrackerActiveTexture::getGLValue()
{
	CC3OpenGLES11StateTrackerEnumeration::getGLValue();
	originalValue -= GL_TEXTURE0;
}


#pragma mark -
#pragma mark CC3OpenGLES11StateTrackerTextureBinding

//@implementation CC3OpenGLES11StateTrackerTextureBinding
//
//-(void) dealloc {
//	textureUnit = nil;		// not retained
//	[super dealloc];
//}
//
//-(id) initForState: (GLenum) qName withParent: (CC3OpenGLES11TextureUnit*) aTexUnit {
//	if ( (self = [super initForState: qName]) ) {
//		textureUnit = aTexUnit;
//	}
//	return self;
//}
//
//+(id) trackerForState: (GLenum) qName withParent: (CC3OpenGLES11TextureUnit*) aTexUnit {
//	return [[[self alloc] initForState: qName withParent: aTexUnit] autorelease];
//}
//
//-(void) getGLValue {
//	[textureUnit activate];
//	[super getGLValue];
//}
//
//-(void) setGLValue {
//	[textureUnit activate];
//	glBindTexture(GL_TEXTURE_2D, value);
//}
//
//-(void) unbind {
//	self.value = 0;
//}
//
//@end

CC3OpenGLES11StateTrackerTextureBinding::CC3OpenGLES11StateTrackerTextureBinding() :
	textureUnit(NULL)
{
}

CC3OpenGLES11StateTrackerTextureBinding::~CC3OpenGLES11StateTrackerTextureBinding()
{
	textureUnit = NULL;
}

CC3OpenGLES11StateTrackerTextureBinding* CC3OpenGLES11StateTrackerTextureBinding::trackerForState(GLenum qName, 
																								  CC3OpenGLES11TextureUnit* aTexUnit)
{
	CC3OpenGLES11StateTrackerTextureBinding* pState = new CC3OpenGLES11StateTrackerTextureBinding;
	if (pState) 
	{
		pState->initForState(qName, aTexUnit);
		pState->autorelease();
	}
	
	return pState;
}

CC3OpenGLES11StateTrackerTextureBinding* CC3OpenGLES11StateTrackerTextureBinding::initForState(GLenum qName, 
																							   CC3OpenGLES11TextureUnit* aTexUnit)
{
	CC3OpenGLES11StateTrackerInteger::initForState(qName, NULL);
	textureUnit = aTexUnit;
	
	return this;
}

void CC3OpenGLES11StateTrackerTextureBinding::unbind()
{
	setValue(0);
}

void CC3OpenGLES11StateTrackerTextureBinding::setGLValue()
{
	textureUnit->activate();
	glBindTexture(GL_TEXTURE_2D, value);
}

void CC3OpenGLES11StateTrackerTextureBinding::getGLValue()
{
	textureUnit->activate();
	CC3OpenGLES11StateTrackerInteger::getGLValue();
}

#pragma mark -
#pragma mark CC3OpenGLES11StateTrackerTexEnvEnumeration

//@implementation CC3OpenGLES11StateTrackerTexEnvEnumeration
//
//-(void) dealloc {
//	textureUnit = nil;		// not retained
//	[super dealloc];
//}
//
//-(id) initForState: (GLenum) qName withParent: (CC3OpenGLES11TextureUnit*) aTexUnit {
//	if ( (self = [super initForState: qName]) ) {
//		textureUnit = aTexUnit;
//	}
//	return self;
//}
//
//+(id) trackerForState: (GLenum) qName withParent: (CC3OpenGLES11TextureUnit*) aTexUnit {
//	return [[[self alloc] initForState: qName withParent: aTexUnit] autorelease];
//}
//
//+(CC3GLESStateOriginalValueHandling) defaultOriginalValueHandling {
//	return kCC3GLESStateOriginalValueReadOnceAndRestore;
//}
//
//-(void) getGLValue {
//	[textureUnit activate];
//	glGetTexEnviv(GL_TEXTURE_ENV, name, (GLint*)&originalValue);
//}
//
//-(void) setGLValue {
//	[textureUnit activate];
//	glTexEnvi(GL_TEXTURE_ENV, name, value);
//}
//
//@end

CC3OpenGLES11StateTrackerTexEnvEnumeration::CC3OpenGLES11StateTrackerTexEnvEnumeration() :
	textureUnit(NULL)
{
}

CC3OpenGLES11StateTrackerTexEnvEnumeration::~CC3OpenGLES11StateTrackerTexEnvEnumeration()
{
	textureUnit = NULL;
}

CC3OpenGLES11StateTrackerTexEnvEnumeration* CC3OpenGLES11StateTrackerTexEnvEnumeration::trackerForState(GLenum qName, 
																										CC3OpenGLES11TextureUnit* aTexUnit)
{
	CC3OpenGLES11StateTrackerTexEnvEnumeration* pState = new CC3OpenGLES11StateTrackerTexEnvEnumeration;
	if (pState) 
	{
		pState->initForState(qName, aTexUnit);
		pState->autorelease();
	}
	
	return pState;
}

CC3OpenGLES11StateTrackerTexEnvEnumeration* CC3OpenGLES11StateTrackerTexEnvEnumeration::initForState(GLenum qName, 
																									 CC3OpenGLES11TextureUnit* aTexUnit)
{
	CC3OpenGLES11StateTrackerEnumeration::initForState(qName, NULL);
	textureUnit = aTexUnit;
	
	return this;
}

CC3GLESStateOriginalValueHandling CC3OpenGLES11StateTrackerTexEnvEnumeration::defaultOriginalValueHandling()
{
	return kCC3GLESStateOriginalValueReadOnceAndRestore;
}

void CC3OpenGLES11StateTrackerTexEnvEnumeration::getGLValue()
{
	textureUnit->activate();
	glGetTexEnviv(GL_TEXTURE_ENV, name, (GLint*)&originalValue);
}

void CC3OpenGLES11StateTrackerTexEnvEnumeration::setGLValue()
{
	textureUnit->activate();
	glTexEnvi(GL_TEXTURE_ENV, name, value);
}


#pragma mark -
#pragma mark CC3OpenGLES11StateTrackerTexEnvColor

//@implementation CC3OpenGLES11StateTrackerTexEnvColor
//
//-(void) dealloc {
//	textureUnit = nil;		// not retained
//	[super dealloc];
//}
//
//-(id) initForState: (GLenum) qName withParent: (CC3OpenGLES11TextureUnit*) aTexUnit {
//	if ( (self = [super initForState: qName]) ) {
//		textureUnit = aTexUnit;
//	}
//	return self;
//}
//
//+(id) trackerForState: (GLenum) qName withParent: (CC3OpenGLES11TextureUnit*) aTexUnit {
//	return [[[self alloc] initForState: qName withParent: aTexUnit] autorelease];
//}
//
//-(void) getGLValue {
//	[textureUnit activate];
//	glGetTexEnvfv(GL_TEXTURE_ENV, name, (GLfloat*)&originalValue);
//}
//
//-(void) setGLValue {
//	[textureUnit activate];
//	glTexEnvfv(GL_TEXTURE_ENV, name, (GLfloat*)&value);
//}
//
//@end

CC3OpenGLES11StateTrackerTexEnvColor::CC3OpenGLES11StateTrackerTexEnvColor() :
textureUnit(NULL)
{
}

CC3OpenGLES11StateTrackerTexEnvColor::~CC3OpenGLES11StateTrackerTexEnvColor()
{
	textureUnit = NULL;
}

CC3OpenGLES11StateTrackerTexEnvColor* CC3OpenGLES11StateTrackerTexEnvColor::trackerForState(GLenum qName, 
																							CC3OpenGLES11TextureUnit* aTexUnit)
{
	CC3OpenGLES11StateTrackerTexEnvColor* pState = new CC3OpenGLES11StateTrackerTexEnvColor;
	if (pState) 
	{
		pState->initForState(qName, aTexUnit);
		pState->autorelease();
	}
	
	return pState;
}

CC3OpenGLES11StateTrackerTexEnvColor* CC3OpenGLES11StateTrackerTexEnvColor::initForState(GLenum qName, 
																						CC3OpenGLES11TextureUnit* aTexUnit)
{
	CC3OpenGLES11StateTrackerColor::initForState(qName, NULL);
	textureUnit = aTexUnit;
	
	return this;
}

void CC3OpenGLES11StateTrackerTexEnvColor::getGLValue()
{
	textureUnit->activate();
	glGetTexEnvfv(GL_TEXTURE_ENV, name, (GLfloat*)&originalValue);
}

void CC3OpenGLES11StateTrackerTexEnvColor::setGLValue()
{
	textureUnit->activate();
	glTexEnvfv(GL_TEXTURE_ENV, name, (GLfloat*)&value);
}

#pragma mark -
#pragma mark CC3OpenGLES11StateTrackerTextureServerCapability

//@implementation CC3OpenGLES11StateTrackerTextureServerCapability
//
//-(void) dealloc {
//	textureUnit = nil;		// not retained
//	[super dealloc];
//}
//
//-(id) initForState: (GLenum) qName withParent: (CC3OpenGLES11TextureUnit*) aTexUnit {
//	if ( (self = [super initForState: qName]) ) {
//		textureUnit = aTexUnit;
//	}
//	return self;
//}
//
//+(id) trackerForState: (GLenum) qName withParent: (CC3OpenGLES11TextureUnit*) aTexUnit {
//	return [[[self alloc] initForState: qName withParent: aTexUnit] autorelease];
//}
//
//-(void) getGLValue {
//	[textureUnit activate];
//	[super getGLValue];
//}
//
//-(void) setGLValue {
//	[textureUnit activate];
//	[super setGLValue];
//}
//
//
//@end

CC3OpenGLES11StateTrackerTextureServerCapability::CC3OpenGLES11StateTrackerTextureServerCapability() :
	textureUnit(NULL)
{
}

CC3OpenGLES11StateTrackerTextureServerCapability::~CC3OpenGLES11StateTrackerTextureServerCapability()
{
	textureUnit = NULL;
}

CC3OpenGLES11StateTrackerTextureServerCapability* CC3OpenGLES11StateTrackerTextureServerCapability::trackerForState(GLenum qName, 
																													CC3OpenGLES11TextureUnit* aTexUnit)
{
	CC3OpenGLES11StateTrackerTextureServerCapability* pState = new CC3OpenGLES11StateTrackerTextureServerCapability;
	if (pState) 
	{
		pState->initForState(qName, aTexUnit);
		pState->autorelease();
	}
	
	return pState;
}

CC3OpenGLES11StateTrackerTextureServerCapability* CC3OpenGLES11StateTrackerTextureServerCapability::initForState(GLenum qName, 
																												 CC3OpenGLES11TextureUnit* aTexUnit)
{
	CC3OpenGLES11StateTrackerServerCapability::initForState(qName, NULL);
	textureUnit = aTexUnit;
	
	return this;
}

void CC3OpenGLES11StateTrackerTextureServerCapability::getGLValue()
{
	textureUnit->activate();
	CC3OpenGLES11StateTrackerServerCapability::getGLValue();
}

void CC3OpenGLES11StateTrackerTextureServerCapability::setGLValue()
{
	textureUnit->activate();
	CC3OpenGLES11StateTrackerServerCapability::setGLValue();
}

#pragma mark -
#pragma mark CC3OpenGLES11StateTrackerTexEnvPointSpriteCapability

//@implementation CC3OpenGLES11StateTrackerTexEnvPointSpriteCapability
//
//-(void) getGLValue {
//	GLint* origIntVal;
//	[textureUnit activate];
//	glGetTexEnviv(GL_POINT_SPRITE_OES, name, (GLint*)&origIntVal);
//	originalValue = (origIntVal != GL_FALSE);
//}
//
//-(void) setGLValue {
//	[textureUnit activate];
//	glTexEnvi(GL_POINT_SPRITE_OES, name, (value ? GL_TRUE : GL_FALSE));
//}
//
//@end

CC3OpenGLES11StateTrackerTexEnvPointSpriteCapability* CC3OpenGLES11StateTrackerTexEnvPointSpriteCapability::trackerForState(GLenum qName, CC3OpenGLES11TextureUnit* aTexUnit)
{
	CC3OpenGLES11StateTrackerTexEnvPointSpriteCapability* pState = new CC3OpenGLES11StateTrackerTexEnvPointSpriteCapability;
	if (pState) 
	{
		pState->initForState(qName, aTexUnit);
		pState->autorelease();
	}
	
	return pState;
}

void CC3OpenGLES11StateTrackerTexEnvPointSpriteCapability::getGLValue()
{
	GLint* origIntVal;
	textureUnit->activate();
	glGetTexEnviv(GL_POINT_SPRITE_OES, name, (GLint*)&origIntVal);
	originalValue = (origIntVal != GL_FALSE);
}

void CC3OpenGLES11StateTrackerTexEnvPointSpriteCapability::setGLValue()
{
	textureUnit->activate();
	glTexEnvi(GL_POINT_SPRITE_OES, name, (value ? GL_TRUE : GL_FALSE));
}

#pragma mark -
#pragma mark CC3OpenGLES11StateTrackerTextureClientCapability

//@implementation CC3OpenGLES11StateTrackerTextureClientCapability
//
//-(void) dealloc {
//	textureUnit = nil;		// not retained
//	[super dealloc];
//}
//
//-(id) initForState: (GLenum) qName withParent: (CC3OpenGLES11TextureUnit*) aTexUnit {
//	if ( (self = [super initForState: qName]) ) {
//		textureUnit = aTexUnit;
//	}
//	return self;
//}
//
//+(id) trackerForState: (GLenum) qName withParent: (CC3OpenGLES11TextureUnit*) aTexUnit {
//	return [[[self alloc] initForState: qName withParent: aTexUnit] autorelease];
//}
//
//-(void) getGLValue {
//	[textureUnit clientActivate];
//	[super getGLValue];
//}
//
//-(void) setGLValue {
//	[textureUnit clientActivate];
//	[super setGLValue];
//}
//
//@end

CC3OpenGLES11StateTrackerTextureClientCapability::CC3OpenGLES11StateTrackerTextureClientCapability() :
	textureUnit(NULL)
{
}

CC3OpenGLES11StateTrackerTextureClientCapability::~CC3OpenGLES11StateTrackerTextureClientCapability()
{
	textureUnit = NULL;
}

CC3OpenGLES11StateTrackerTextureClientCapability* CC3OpenGLES11StateTrackerTextureClientCapability::trackerForState(GLenum qName, 
																													CC3OpenGLES11TextureUnit* aTexUnit)
{
	CC3OpenGLES11StateTrackerTextureClientCapability* pState = new CC3OpenGLES11StateTrackerTextureClientCapability;
	if (pState) 
	{
		pState->initForState(qName, aTexUnit);
		pState->autorelease();
	}
	
	return pState;
}

CC3OpenGLES11StateTrackerTextureClientCapability* CC3OpenGLES11StateTrackerTextureClientCapability::initForState(GLenum qName, 
																												 CC3OpenGLES11TextureUnit* aTexUnit)
{
	CC3OpenGLES11StateTrackerClientCapability::initForState(qName, NULL);
	textureUnit = aTexUnit;
	
	return this;
}

void CC3OpenGLES11StateTrackerTextureClientCapability::getGLValue()
{
	textureUnit->clientActivate();
	CC3OpenGLES11StateTrackerClientCapability::getGLValue();
}

void CC3OpenGLES11StateTrackerTextureClientCapability::setGLValue()
{
	textureUnit->clientActivate();
	CC3OpenGLES11StateTrackerClientCapability::setGLValue();
}

#pragma mark -
#pragma mark CC3OpenGLES11StateTrackerVertexTexCoordsPointer

//@implementation CC3OpenGLES11StateTrackerVertexTexCoordsPointer
//
//-(void) dealloc {
//	textureUnit = nil;		// not retained
//	[super dealloc];
//}
//
//-(id) initWithParent: (CC3OpenGLES11TextureUnit*) aTexUnit {
//	if ( (self = [super init]) ) {
//		textureUnit = aTexUnit;
//	}
//	return self;
//}
//
//+(id) trackerWithParent: (CC3OpenGLES11TextureUnit*) aTexUnit {
//	return [[[self alloc] initWithParent: aTexUnit] autorelease];
//}
//
//-(void) initializeTrackers {
//	self.elementSize = [CC3OpenGLES11StateTrackerInteger trackerForState: GL_TEXTURE_COORD_ARRAY_SIZE];
//	self.elementType = [CC3OpenGLES11StateTrackerEnumeration trackerForState: GL_TEXTURE_COORD_ARRAY_TYPE];
//	self.elementStride = [CC3OpenGLES11StateTrackerInteger trackerForState: GL_TEXTURE_COORD_ARRAY_STRIDE];
//	self.elementPointer = [CC3OpenGLES11StateTrackerPointer tracker];
//}
//
//-(void) setGLValues {
//	[textureUnit clientActivate];
//	glTexCoordPointer(elementSize.value, elementType.value, elementStride.value, elementPointer.value);
//}
//
//-(void) open {
//	[textureUnit clientActivate];
//	[super open];
//}
//
//@end

CC3OpenGLES11StateTrackerVertexTexCoordsPointer::CC3OpenGLES11StateTrackerVertexTexCoordsPointer() :
	textureUnit(NULL)
{
}

CC3OpenGLES11StateTrackerVertexTexCoordsPointer::~CC3OpenGLES11StateTrackerVertexTexCoordsPointer()
{
	textureUnit = NULL;
}

CC3OpenGLES11StateTrackerVertexTexCoordsPointer* CC3OpenGLES11StateTrackerVertexTexCoordsPointer::trackerWithParent(CC3OpenGLES11TextureUnit* aTexUni)
{
	CC3OpenGLES11StateTrackerVertexTexCoordsPointer* pState = new CC3OpenGLES11StateTrackerVertexTexCoordsPointer;
	if (pState) 
	{
		pState->init();
		pState->initWithParent(aTexUni);
		//pState->initializeTrackers();
		pState->autorelease();
	}
	
	return pState;
}

CC3OpenGLES11StateTrackerVertexTexCoordsPointer* CC3OpenGLES11StateTrackerVertexTexCoordsPointer::initWithParent(CC3OpenGLES11TextureUnit* aTexUnit)
{
	textureUnit = aTexUnit;
	
	return this;
}

void CC3OpenGLES11StateTrackerVertexTexCoordsPointer::initializeTrackers()
{
	setElementSize(CC3OpenGLES11StateTrackerInteger::trackerForState(GL_TEXTURE_COORD_ARRAY_SIZE, NULL));
	setElementType(CC3OpenGLES11StateTrackerEnumeration::trackerForState(GL_TEXTURE_COORD_ARRAY_TYPE));
	setElementStride(CC3OpenGLES11StateTrackerInteger::trackerForState(GL_TEXTURE_COORD_ARRAY_STRIDE, NULL));
	setElementPointer(CC3OpenGLES11StateTrackerPointer::tracker());
}

void CC3OpenGLES11StateTrackerVertexTexCoordsPointer::setGLValues()
{
	textureUnit->clientActivate();
	glTexCoordPointer(elementSize->getValue(), elementType->getValue(), elementStride->getValue(), elementPointer->getValue());
}

void CC3OpenGLES11StateTrackerVertexTexCoordsPointer::open()
{
	textureUnit->clientActivate();
	CC3OpenGLES11StateTrackerVertexPointer::open();
}

#pragma mark -
#pragma mark CC3OpenGLES11TextureMatrixStack

//@implementation CC3OpenGLES11TextureMatrixStack
//
//-(void) dealloc {
//	textureUnit = nil;		// not retained
//	[super dealloc];
//}
//
//-(id) initWithMode: (GLenum) matrixMode
//		andTopName: (GLenum) tName
//	  andDepthName: (GLenum) dName
//	andModeTracker: (CC3OpenGLES11StateTrackerEnumeration*) tracker
//		withParent: (CC3OpenGLES11TextureUnit*) aTexUnit {
//	if ( (self = [super initWithMode: matrixMode
//						  andTopName: tName
//						andDepthName: dName
//					  andModeTracker: tracker]) ) {
//		textureUnit = aTexUnit;
//	}
//	return self;
//}
//
//+(id) trackerWithMode: (GLenum) matrixMode
//		   andTopName: (GLenum) tName
//		 andDepthName: (GLenum) dName
//	   andModeTracker: (CC3OpenGLES11StateTrackerEnumeration*) tracker
//		   withParent: (CC3OpenGLES11TextureUnit*) aTexUnit {
//	return [[[self alloc] initWithMode: matrixMode
//							andTopName: tName
//						  andDepthName: dName
//						andModeTracker: tracker
//							withParent: aTexUnit] autorelease];
//}
//
//-(void) activate {
//	[super activate];
//	[textureUnit activate];
//}
//
//@end

CC3OpenGLES11TextureMatrixStack::CC3OpenGLES11TextureMatrixStack() :
	textureUnit(NULL)
{
}

CC3OpenGLES11TextureMatrixStack::~CC3OpenGLES11TextureMatrixStack()
{
	textureUnit = NULL;
}

CC3OpenGLES11TextureMatrixStack* CC3OpenGLES11TextureMatrixStack::trackerWithMode(GLenum matrixMode,
														GLenum tName,
														GLenum dName,
														CC3OpenGLES11StateTrackerEnumeration* tracker,
														CC3OpenGLES11TextureUnit* aTexUnit)
{
	CC3OpenGLES11TextureMatrixStack* pState = new CC3OpenGLES11TextureMatrixStack;
	if (pState) 
	{
		pState->initWithMode(matrixMode, tName, dName, tracker, aTexUnit);
		pState->autorelease();
	}
	
	return pState;
}

CC3OpenGLES11TextureMatrixStack* CC3OpenGLES11TextureMatrixStack::initWithMode(GLenum matrixMode,
											  GLenum tName,
											  GLenum dName,
											  CC3OpenGLES11StateTrackerEnumeration* tracker,
											  CC3OpenGLES11TextureUnit* aTexUnit)
{
	CC3OpenGLES11MatrixStack::initWithMode(matrixMode, tName, dName, tracker);
	textureUnit = aTexUnit;
	
	return this;
}

void CC3OpenGLES11TextureMatrixStack::activate()
{
	CC3OpenGLES11MatrixStack::activate();
	textureUnit->activate();
}

#pragma mark -
#pragma mark CC3OpenGLES11TextureUnit

//@implementation CC3OpenGLES11TextureUnit
//
//@synthesize texture2D;
//@synthesize textureCoordArray;
//@synthesize textureCoordinates;
//@synthesize textureBinding;
//@synthesize textureEnvironmentMode;
//@synthesize combineRGBFunction;
//@synthesize rgbSource0;
//@synthesize rgbSource1;
//@synthesize rgbSource2;
//@synthesize rgbOperand0;
//@synthesize rgbOperand1;
//@synthesize rgbOperand2;
//@synthesize combineAlphaFunction;
//@synthesize alphaSource0;
//@synthesize alphaSource1;
//@synthesize alphaSource2;
//@synthesize alphaOperand0;
//@synthesize alphaOperand1;
//@synthesize alphaOperand2;
//@synthesize color;
//@synthesize pointSpriteCoordReplace;
//@synthesize matrixStack;
//
//-(void) dealloc {
//	[texture2D release];
//	[textureCoordArray release];
//	[textureCoordinates release];
//	[textureBinding release];
//	[textureEnvironmentMode release];
//	[combineRGBFunction release];
//	[rgbSource0 release];
//	[rgbSource1 release];
//	[rgbSource2 release];
//	[rgbOperand0 release];
//	[rgbOperand1 release];
//	[rgbOperand2 release];
//	[combineAlphaFunction release];
//	[alphaSource0 release];
//	[alphaSource1 release];
//	[alphaSource2 release];
//	[alphaOperand0 release];
//	[alphaOperand1 release];
//	[alphaOperand2 release];
//	[color release];
//	[pointSpriteCoordReplace release];
//	[matrixStack release];
//
//	[super dealloc];
//}
//
//-(id) initWithTextureUnitIndex: (GLuint) texUnit withParent: (CC3OpenGLES11Textures*) aTexState {
//	if ( (self = [super initMinimal]) ) {
//		texturesState = aTexState;
//		textureUnitIndex = texUnit;
//		[self initializeTrackers];
//	}
//	return self;
//}
//
//+(id) trackerWithTextureUnitIndex: (GLuint) texUnit withParent: (CC3OpenGLES11Textures*) aTexState {
//	return [[[self alloc] initWithTextureUnitIndex: texUnit withParent: aTexState] autorelease];
//}
//
//-(void) initializeTrackers {
//	self.texture2D = [CC3OpenGLES11StateTrackerTextureServerCapability trackerForState: GL_TEXTURE_2D
//																			withParent: self];
//	self.textureCoordArray = [CC3OpenGLES11StateTrackerTextureClientCapability trackerForState: GL_TEXTURE_COORD_ARRAY
//																					withParent: self];
//	self.textureCoordinates = [CC3OpenGLES11StateTrackerVertexTexCoordsPointer trackerWithParent: self];
//	self.textureBinding = [CC3OpenGLES11StateTrackerTextureBinding trackerForState: GL_TEXTURE_BINDING_2D
//																		withParent: self];
//	self.textureEnvironmentMode = [CC3OpenGLES11StateTrackerTexEnvEnumeration trackerForState: GL_TEXTURE_ENV_MODE
//																				   withParent: self];
//	self.combineRGBFunction = [CC3OpenGLES11StateTrackerTexEnvEnumeration trackerForState: GL_COMBINE_RGB
//																			   withParent: self];
//	self.rgbSource0 = [CC3OpenGLES11StateTrackerTexEnvEnumeration trackerForState: GL_SRC0_RGB
//																	   withParent: self];
//	self.rgbSource1 = [CC3OpenGLES11StateTrackerTexEnvEnumeration trackerForState: GL_SRC1_RGB
//																	   withParent: self];
//	self.rgbSource2 = [CC3OpenGLES11StateTrackerTexEnvEnumeration trackerForState: GL_SRC2_RGB
//																	   withParent: self];
//	self.rgbOperand0 = [CC3OpenGLES11StateTrackerTexEnvEnumeration trackerForState: GL_OPERAND0_RGB
//																		withParent: self];
//	self.rgbOperand1 = [CC3OpenGLES11StateTrackerTexEnvEnumeration trackerForState: GL_OPERAND1_RGB
//																		withParent: self];
//	self.rgbOperand2 = [CC3OpenGLES11StateTrackerTexEnvEnumeration trackerForState: GL_OPERAND2_RGB
//																		withParent: self];
//	self.combineAlphaFunction = [CC3OpenGLES11StateTrackerTexEnvEnumeration trackerForState: GL_COMBINE_ALPHA
//																				 withParent: self];
//	self.alphaSource0 = [CC3OpenGLES11StateTrackerTexEnvEnumeration trackerForState: GL_SRC0_ALPHA
//																		 withParent: self];
//	self.alphaSource1 = [CC3OpenGLES11StateTrackerTexEnvEnumeration trackerForState: GL_SRC1_ALPHA
//																		 withParent: self];
//	self.alphaSource2 = [CC3OpenGLES11StateTrackerTexEnvEnumeration trackerForState: GL_SRC2_ALPHA
//																		 withParent: self];
//	self.alphaOperand0 = [CC3OpenGLES11StateTrackerTexEnvEnumeration trackerForState: GL_OPERAND0_ALPHA
//																		  withParent: self];
//	self.alphaOperand1 = [CC3OpenGLES11StateTrackerTexEnvEnumeration trackerForState: GL_OPERAND1_ALPHA
//																		  withParent: self];
//	self.alphaOperand2 = [CC3OpenGLES11StateTrackerTexEnvEnumeration trackerForState: GL_OPERAND2_ALPHA
//																		  withParent: self];
//	self.color = [CC3OpenGLES11StateTrackerTexEnvColor trackerForState: GL_TEXTURE_ENV_COLOR
//															withParent: self];
//	self.pointSpriteCoordReplace = [CC3OpenGLES11StateTrackerTexEnvPointSpriteCapability trackerForState: GL_COORD_REPLACE_OES
//																							  withParent: self];
//	self.matrixStack = [CC3OpenGLES11TextureMatrixStack trackerWithMode: GL_TEXTURE 
//															 andTopName: GL_TEXTURE_MATRIX
//														   andDepthName: GL_TEXTURE_STACK_DEPTH
//														 andModeTracker: [CC3OpenGLES11Engine engine].matrices.mode
//															 withParent: self];
//}
//
//-(void) open {
//	LogTrace("Opening %@", [self class]);
//	[texture2D open];
//	[textureCoordArray open];
//	[textureCoordinates open];
//	[textureBinding open];
//	[textureEnvironmentMode open];
//	[combineRGBFunction open];
//	[rgbSource0 open];
//	[rgbSource1 open];
//	[rgbSource2 open];
//	[rgbOperand0 open];
//	[rgbOperand1 open];
//	[rgbOperand2 open];
//	[combineAlphaFunction open];
//	[alphaSource0 open];
//	[alphaSource1 open];
//	[alphaSource2 open];
//	[alphaOperand0 open];
//	[alphaOperand1 open];
//	[alphaOperand2 open];
//	[color open];
//	[pointSpriteCoordReplace open];
//	[matrixStack open];
//}
//
//-(void) close {
//	LogTrace("Closing %@", [self class]);
//	[texture2D close];
//	[textureCoordArray close];
//	[textureCoordinates close];
//	[textureBinding close];
//	[textureEnvironmentMode close];
//	[combineRGBFunction close];
//	[rgbSource0 close];
//	[rgbSource1 close];
//	[rgbSource2 close];
//	[rgbOperand0 close];
//	[rgbOperand1 close];
//	[rgbOperand2 close];
//	[combineAlphaFunction close];
//	[alphaSource0 close];
//	[alphaSource1 close];
//	[alphaSource2 close];
//	[alphaOperand0 close];
//	[alphaOperand1 close];
//	[alphaOperand2 close];
//	[color close];
//	[pointSpriteCoordReplace close];
//	[matrixStack close];
//}
//
//-(void) activate {
//	texturesState.activeTexture.value = textureUnitIndex;
//}
//
//-(void) clientActivate {
//	texturesState.clientActiveTexture.value = textureUnitIndex;
//}
//
//-(GLenum) glEnumValue {
//	return GL_TEXTURE0 + textureUnitIndex;
//}
//
//-(NSString*) description {
//	NSMutableString* desc = [NSMutableString stringWithCapacity: 1000];
//	[desc appendFormat: @"%@ for %@:", [self class], NSStringFromGLEnum(self.glEnumValue)];
//	[desc appendFormat: @"\n    %@", texture2D];
//	[desc appendFormat: @"\n    %@", textureCoordArray];
//	[desc appendFormat: @"\n    %@", textureCoordinates];
//	[desc appendFormat: @"\n    %@", textureBinding];
//	[desc appendFormat: @"\n    %@", textureEnvironmentMode];
//	[desc appendFormat: @"\n    %@", combineRGBFunction];
//	[desc appendFormat: @"\n    %@", rgbSource0];
//	[desc appendFormat: @"\n    %@", rgbSource1];
//	[desc appendFormat: @"\n    %@", rgbSource2];
//	[desc appendFormat: @"\n    %@", rgbOperand0];
//	[desc appendFormat: @"\n    %@", rgbOperand1];
//	[desc appendFormat: @"\n    %@", rgbOperand2];
//	[desc appendFormat: @"\n    %@", combineAlphaFunction];
//	[desc appendFormat: @"\n    %@", alphaSource0];
//	[desc appendFormat: @"\n    %@", alphaSource1];
//	[desc appendFormat: @"\n    %@", alphaSource2];
//	[desc appendFormat: @"\n    %@", alphaOperand0];
//	[desc appendFormat: @"\n    %@", alphaOperand1];
//	[desc appendFormat: @"\n    %@", alphaOperand2];
//	[desc appendFormat: @"\n    %@", color];
//	[desc appendFormat: @"\n    %@", pointSpriteCoordReplace];
//	return desc;
//}
//
//@end

CC3OpenGLES11TextureUnit::CC3OpenGLES11TextureUnit() :
	texture2D(NULL),
	textureCoordArray(NULL),
	textureCoordinates(NULL),
	textureBinding(NULL),
	textureEnvironmentMode(NULL),
	combineRGBFunction(NULL),
	rgbSource0(NULL),
	rgbSource1(NULL),
	rgbSource2(NULL),
	rgbOperand0(NULL),
	rgbOperand1(NULL),
	rgbOperand2(NULL),
	combineAlphaFunction(NULL),
	alphaSource0(NULL),
	alphaSource1(NULL),
	alphaOperand0(NULL),
	alphaOperand1(NULL),
	alphaOperand2(NULL),
	color(NULL),
	pointSpriteCoordReplace(NULL),
	matrixStack(NULL)
{
}

CC3OpenGLES11TextureUnit::~CC3OpenGLES11TextureUnit()
{
	texture2D->release();
	textureCoordArray->release();
	textureCoordinates->release();
	textureBinding->release();
	textureEnvironmentMode->release();
	combineRGBFunction->release();
	rgbSource0->release();
	rgbSource1->release();
	rgbSource2->release();
	rgbOperand0->release();
	rgbOperand1->release();
	rgbOperand2->release();
	combineAlphaFunction->release();
	alphaSource0->release();
	alphaSource1->release();
	alphaSource2->release();
	alphaOperand0->release();
	alphaOperand1->release();
	alphaOperand2->release();
	color->release();
	pointSpriteCoordReplace->release();
	matrixStack->release();
}

CC3OpenGLES11TextureUnit* CC3OpenGLES11TextureUnit::trackerWithTextureUnitIndex(GLuint texUnit, CC3OpenGLES11Textures* aTexState)
{
	CC3OpenGLES11TextureUnit* pUnit = new CC3OpenGLES11TextureUnit;
	if (pUnit) 
	{
		pUnit->initWithTextureUnitIndex(texUnit, aTexState);
		pUnit->autorelease();
	}
	
	return pUnit;
}

CC3OpenGLES11TextureUnit* CC3OpenGLES11TextureUnit::initWithTextureUnitIndex(GLuint texUnit, CC3OpenGLES11Textures* aTexState)
{
	CC3OpenGLES11StateTrackerManager::initMinimal();
	texturesState = aTexState;
	textureUnitIndex = texUnit;
	initializeTrackers();
	
	return this;
}

void CC3OpenGLES11TextureUnit::activate()
{
	texturesState->getActiveTexture()->setValue(textureUnitIndex);
}

void CC3OpenGLES11TextureUnit::clientActivate()
{
	texturesState->getClientActiveTexture()->setValue(textureUnitIndex);
}

void CC3OpenGLES11TextureUnit::initializeTrackers()
{
	setTexture2D(CC3OpenGLES11StateTrackerTextureServerCapability::trackerForState(GL_TEXTURE_2D, this));
	setTextureCoordArray(CC3OpenGLES11StateTrackerTextureClientCapability::trackerForState(GL_TEXTURE_COORD_ARRAY, this));
	setTextureCoordinates(CC3OpenGLES11StateTrackerVertexTexCoordsPointer::trackerWithParent(this));
	setTextureBinding(CC3OpenGLES11StateTrackerTextureBinding::trackerForState(GL_TEXTURE_BINDING_2D, this));
	setTextureEnvironmentMode(CC3OpenGLES11StateTrackerTexEnvEnumeration::trackerForState(GL_TEXTURE_ENV_MODE, this));
	setCombineRGBFunction(CC3OpenGLES11StateTrackerTexEnvEnumeration::trackerForState(GL_COMBINE_RGB, this));
	setRgbSource0(CC3OpenGLES11StateTrackerTexEnvEnumeration::trackerForState(GL_SRC0_RGB, this));
	setRgbSource1(CC3OpenGLES11StateTrackerTexEnvEnumeration::trackerForState(GL_SRC1_RGB, this));
	setRgbSource2(CC3OpenGLES11StateTrackerTexEnvEnumeration::trackerForState(GL_SRC2_RGB, this));
	setRgbOperand0(CC3OpenGLES11StateTrackerTexEnvEnumeration::trackerForState(GL_OPERAND0_RGB, this));
	setRgbOperand1(CC3OpenGLES11StateTrackerTexEnvEnumeration::trackerForState(GL_OPERAND1_RGB, this));
	setRgbOperand2(CC3OpenGLES11StateTrackerTexEnvEnumeration::trackerForState(GL_OPERAND2_RGB, this));
	setCombineAlphaFunction(CC3OpenGLES11StateTrackerTexEnvEnumeration::trackerForState(GL_COMBINE_ALPHA, this));
	setAlphaSource0(CC3OpenGLES11StateTrackerTexEnvEnumeration::trackerForState(GL_SRC0_ALPHA, this));
	setAlphaSource1(CC3OpenGLES11StateTrackerTexEnvEnumeration::trackerForState(GL_SRC1_ALPHA, this));
	setAlphaSource2(CC3OpenGLES11StateTrackerTexEnvEnumeration::trackerForState(GL_SRC2_ALPHA, this));
	setAlphaOperand0(CC3OpenGLES11StateTrackerTexEnvEnumeration::trackerForState(GL_OPERAND0_ALPHA, this));
	setAlphaOperand1(CC3OpenGLES11StateTrackerTexEnvEnumeration::trackerForState(GL_OPERAND1_ALPHA, this));
	setAlphaOperand2(CC3OpenGLES11StateTrackerTexEnvEnumeration::trackerForState(GL_OPERAND2_ALPHA, this));
	setColor(CC3OpenGLES11StateTrackerTexEnvColor::trackerForState(GL_TEXTURE_ENV_COLOR, this));
	setPointSpriteCoordReplace(CC3OpenGLES11StateTrackerTexEnvPointSpriteCapability::trackerForState(GL_COORD_REPLACE_OES, this));
	setMatrixStack(CC3OpenGLES11TextureMatrixStack::trackerWithMode(GL_TEXTURE, 
																   GL_TEXTURE_MATRIX, 
																   GL_TEXTURE_STACK_DEPTH,
																   CC3OpenGLES11Engine::engine()->getMatrices()->getMode(),
																   this));
}

void CC3OpenGLES11TextureUnit::open()
{
	//LogTrace("Opening %@", [self class]);
	texture2D->open();
	textureCoordArray->open();
	textureCoordinates->open();
	textureBinding->open();
	textureEnvironmentMode->open();
	combineRGBFunction->open();
	rgbSource0->open();
	rgbSource1->open();
	rgbSource2->open();
	rgbOperand0->open();
	rgbOperand1->open();
	rgbOperand2->open();
	combineAlphaFunction->open();
	alphaSource0->open();
	alphaSource1->open();
	alphaSource2->open();
	alphaOperand0->open();
	alphaOperand1->open();
	alphaOperand2->open();
	color->open();
	pointSpriteCoordReplace->open();
	matrixStack->open();
}

void CC3OpenGLES11TextureUnit::close()
{
	//LogTrace("Closing %@", [self class]);
	texture2D->close();
	textureCoordArray->close();
	textureCoordinates->close();
	textureBinding->close();
	textureEnvironmentMode->close();
	combineRGBFunction->close();
	rgbSource0->close();
	rgbSource1->close();
	rgbSource2->close();
	rgbOperand0->close();
	rgbOperand1->close();
	rgbOperand2->close();
	combineAlphaFunction->close();
	alphaSource0->close();
	alphaSource1->close();
	alphaSource2->close();
	alphaOperand0->close();
	alphaOperand1->close();
	alphaOperand2->close();
	color->close();
	pointSpriteCoordReplace->close();
	matrixStack->close();
}

GLenum CC3OpenGLES11TextureUnit::glEnumValue()
{
	return GL_TEXTURE0 + textureUnitIndex;
}

#pragma mark -
#pragma mark CC3OpenGLES11Textures

//@interface CC3OpenGLES11Textures (TemplateMethods)
//-(CC3OpenGLES11TextureUnit*) makeTextureUnit: (GLuint) texUnit;
//@end
//
//@implementation CC3OpenGLES11Textures
//
//@synthesize activeTexture;
//@synthesize clientActiveTexture;
//@synthesize textureUnits;
//
//-(void) dealloc {
//	[activeTexture release];
//	[clientActiveTexture release];
//	[textureUnits release];
//	
//	[super dealloc];
//}
//
//-(GLuint) textureUnitCount {
//	return textureUnits ? textureUnits.count : 0;
//}
//
//// The minimum number of GL texture unit trackers to create initially.
//// See the description of the class-side minimumTextureUnits property.
//GLuint minimumTextureUnits = 1;
//
//+(GLuint) minimumTextureUnits {
//	return minimumTextureUnits;
//}
//
//+(void) setMinimumTextureUnits: (GLuint) minTexUnits {
//	minimumTextureUnits = minTexUnits;
//}
//
///** Template method returns an autoreleased instance of a texture unit tracker. */
//-(CC3OpenGLES11TextureUnit*) makeTextureUnit: (GLuint) texUnit {
//	return [CC3OpenGLES11TextureUnit trackerWithTextureUnitIndex: texUnit withParent: self];
//}
//
//-(CC3OpenGLES11TextureUnit*) textureUnitAt: (GLuint) texUnit {
//	// If the requested texture unit hasn't been allocated yet, add it.
//	if (texUnit >= self.textureUnitCount) {
//		// Make sure we don't add beyond the max number of texture units for the platform
//		GLuint platformMaxTexUnits = [CC3OpenGLES11Engine engine].platform.maxTextureUnits.value;
//		GLuint tuMax = MIN(texUnit, platformMaxTexUnits);
//
//		// Add all texture units between the current count and the requested texture unit.
//		for (GLuint i = self.textureUnitCount; i <= tuMax; i++) {
//			CC3OpenGLES11TextureUnit* tu = [self makeTextureUnit: i];
//			[tu open];		// Read the initial values
//			[textureUnits addObject: tu];
//			LogTrace(@"%@ added texture unit %u:\n%@", [self class], i, tu);
//		}
//	}
//	return [textureUnits objectAtIndex: texUnit];
//}
//
//-(void) initializeTrackers {
//	self.activeTexture = [CC3OpenGLES11StateTrackerActiveTexture trackerForState: GL_ACTIVE_TEXTURE
//																andGLSetFunction: glActiveTexture];
//	self.clientActiveTexture = [CC3OpenGLES11StateTrackerActiveTexture trackerForState: GL_CLIENT_ACTIVE_TEXTURE
//																	  andGLSetFunction: glClientActiveTexture];
//
//	// Start with the min number of texture unit trackers. Add more as requested by textureUnitAt:.
//	self.textureUnits = [NSMutableArray array];
//	for (GLuint i = 0; i < minimumTextureUnits; i++) {
//		[textureUnits addObject: [self makeTextureUnit: i]];
//	}
//}
//
//-(void) open {
//	LogTrace("Opening %@", [self class]);
//	[activeTexture open];
//	[clientActiveTexture open];
//	[self openTrackers: textureUnits];
//}
//
//-(void) close {
//	LogTrace("Closing %@", [self class]);
//	[self closeTrackers: textureUnits];
//	[activeTexture close];					// Close after texture units because they can change this.
//	[clientActiveTexture close];			// Close after texture units because they can change this.
//}
//
//-(NSString*) description {
//	NSMutableString* desc = [NSMutableString stringWithCapacity:10000];
//	[desc appendFormat: @"%@:", [self class]];
//	[desc appendFormat: @"\n    %@", activeTexture];
//	[desc appendFormat: @"\n    %@", clientActiveTexture];
//	for (id tu in textureUnits) {
//		[desc appendFormat: @"\n%@", tu];
//	}
//	return desc;
//}
//
//@end

GLuint CC3OpenGLES11Textures::minimumTextureUnitsValue = 1;

CC3OpenGLES11Textures::CC3OpenGLES11Textures() :
	activeTexture(NULL),
	clientActiveTexture(NULL),
	textureUnits(NULL)
{
	
}

CC3OpenGLES11Textures::~CC3OpenGLES11Textures()
{
	activeTexture->release();
	clientActiveTexture->release();
	textureUnits->release();
}

CC3OpenGLES11Textures* CC3OpenGLES11Textures::tracker()
{
	CC3OpenGLES11Textures* pState = new CC3OpenGLES11Textures;
	if (pState) 
	{
		pState->initializeTrackers();
		pState->autorelease();
	}
	
	return pState;
}

CC3OpenGLES11TextureUnit* CC3OpenGLES11Textures::textureUnitAt(GLuint texUnit)
{
	// If the requested texture unit hasn't been allocated yet, add it.
	if (texUnit >= textureUnitCount()) 
	{
		// Make sure we don't add beyond the max number of texture units for the platform
		GLuint platformMaxTexUnits = CC3OpenGLES11Engine::engine()->getPlatform()->getMaxTextureUnits()->getValue();
		GLuint tuMax = MIN(texUnit, platformMaxTexUnits);
		
		// Add all texture units between the current count and the requested texture unit.
		for (GLuint i = textureUnitCount(); i <= tuMax; i++) 
		{
			CC3OpenGLES11TextureUnit* tu = (CC3OpenGLES11TextureUnit*)makeTextureUnit(i);
			tu->open();		// Read the initial values
			textureUnits->addObject(tu);
			//LogTrace(@"%@ added texture unit %u:\n%@", [self class], i, tu);
		}
	}
	return (CC3OpenGLES11TextureUnit*)(textureUnits->objectAtIndex(texUnit));
}

CC3OpenGLES11TextureUnit* CC3OpenGLES11Textures::makeTextureUnit(GLuint texUnit)
{
	return CC3OpenGLES11TextureUnit::trackerWithTextureUnitIndex(texUnit, this);
}

GLuint CC3OpenGLES11Textures::textureUnitCount()
{
	return textureUnits ? textureUnits->count() : 0;
}

GLuint CC3OpenGLES11Textures::minimumTextureUnits()
{
	return minimumTextureUnitsValue;
}

void CC3OpenGLES11Textures::setMinimumTextureUnits(GLuint minTexUnits)
{
	minimumTextureUnitsValue = minTexUnits;
}

void CC3OpenGLES11Textures::initializeTrackers()
{
	setActiveTexture(CC3OpenGLES11StateTrackerActiveTexture::trackerForState(GL_ACTIVE_TEXTURE, glActiveTexture));
	setClientActiveTexture(CC3OpenGLES11StateTrackerActiveTexture::trackerForState(GL_CLIENT_ACTIVE_TEXTURE, glClientActiveTexture));
	
	// Start with the min number of texture unit trackers. Add more as requested by textureUnitAt:.
	setTextureUnits(cocos2d::CCArray::array());
	for (GLuint i = 0; i < minimumTextureUnits(); i++) 
	{
		textureUnits->addObject(makeTextureUnit(i));
	}
}

void CC3OpenGLES11Textures::open()
{
	//LogTrace("Opening %@", [self class]);
	activeTexture->open();
	clientActiveTexture->open();
	openTrackers(textureUnits);
}

void CC3OpenGLES11Textures::close()
{
	//LogTrace("Closing %@", [self class]);
	closeTrackers(textureUnits);
	activeTexture->close();					// Close after texture units because they can change this.
	clientActiveTexture->close();			// Close after texture units because they can change this.
}


